#include "pwext.hpp"
#include <list>

// [[ex05fb]]
// DEBUG descr Another simple-minded implementation of weak references causes a deadlock.
class someobj
{
public:
	someobj() : other_(0)
	{ }

	void linkOther(someobj *ob)
	{
		pw::lockmutex lm(mutex_);
		other_ = ob;
	}
	void unlinkFromOther()
	{
		pw::lockmutex lm(mutex_);
		someobj *ob = other_;
		other_ = 0;
		if (ob != 0)
			ob->unlinkOther();
	}
	bool someMethod()
	{
		// just for demonstration
		return true;
	}
	// returns true if the call succeeded
	bool callMethodOnOther()
	{
		pw::lockmutex lm(mutex_);
		if (other_ == 0)
			return false;
		else
			return other_->someMethod();
	}
protected:
	// not called from outside this class any more
	void unlinkOther()
	{
		pw::lockmutex lm(mutex_);
		other_ = 0;
	}

	pw::pmutex mutex_;
	someobj *other_;
};

// DEBUG from
void makeWorkerThread(someobj *o);

void run()
{
// DEBUG to
// ... creation ...
	someobj *a = new someobj;
	someobj *b = new someobj;
	a->linkOther(b);
	b->linkOther(a);
	makeWorkerThread(a);
	makeWorkerThread(b);
// DEBUG from
}

class worker : public pw::pwthread
{
public:
	worker(someobj *o) :
		o_(o)
	{ }

   virtual void *execute()
   {
// DEBUG to

// ... in the worker thread ...
// the thread keeps the someobj in the member o_
	// ... call a method on the other object ...
	bool result = o_->callMethodOnOther();
	// ... destroy our object ...
	o_->unlinkFromOther();
	delete o_;
// END
// DEBUG from
	o_ = 0;
	return 0;
	}
protected:
	someobj *o_;
};

std::list <worker *> workers;

void makeWorkerThread(someobj *o)
{
	workers.push_back(new worker(o));
}
